Shiny.addCustomMessageHandler("parallelcoordinates_values", function (message) {

    //TRATAMENTO INICIAL DOS DADOS - TRANSPOSIÇÃO
    var dataset = message;
    var numero_dados = dataset.Acidentes.length;
    var dado = { Acidentes: null, Sexo: null, Hora: null };
    var vetorDados = [];
    var traits = ['Acidentes', 'Sexo', 'Hora', 'Media de Idade'];
    var o;
    for (o = 0; o < numero_dados; o++) {
        traits.forEach(function (string) {
            dado[string] = dataset[string][o];
        });
        vetorDados.push(dado);
        dado = {};
    }

    var parcoordstable = d3.select("#parallelcoordinates_table table");
    var checkboxes = d3.select("#parallelcoordinates_area")
        .append("div")
        .attr("id", "parallel-coordinates-switch");

    function toggleAxis(checkBox, trait) {
        if (checkBox.checked == true) {
            if (!traits.includes(trait))
                traits.push(trait);
        }
        if (checkBox.checked == false) {
            var i = traits.indexOf(trait);
            traits.splice(i, 1);
        }
        d3.select("#parallelcoordinates_area svg").remove();
        loadChart();
    }

    traits.forEach(function (trait) {
        checkboxes.append("input")
            .attr("type", "checkbox")
            .attr("id", trait)
            .attr("value", trait)
            .attr("checked", true)
            .on("click", function () {
                toggleAxis(this, trait);
            });
        checkboxes.append("text")
            .text(trait);
    });

    function loadChart() {
        dragging = {};
        var background;
        var m = [50, 80, 50, 100],
            w = 500 - m[1] - m[3],
            h = 400 - m[0] - m[2];
        var line = d3.line(),
            axis = d3.axisLeft(),
            foreground;
        var parcoords = d3.select("#parallelcoordinates_area").append("svg")
            .attr("width", w + m[1] + m[3])
            .attr("height", h + m[0] + m[2])
            .append("g")
            .attr("transform", "translate(" + m[3] +
                  "," + m[0] + ")");

        // Create a scale and brush for each trait
        var x = d3.scalePoint().domain(traits).range([0, w]),
            y = {};

        traits.forEach(function (col) {
            vetorDados.forEach(function (p) {
                p[col] = +p[col];
            });
            y[col] = d3.scaleLinear()
                .domain(d3.extent(vetorDados, function (p) {
                    return p[col];
                }))
                .range([h, 0]);

            //CREATE BRUSH
            y[col].brush = d3.brushY()
                .extent([[-7, y[col].range()[1]],
			 [7, y[col].range()[0]]
			])
                .on("start", brushstart)
                .on("brush", brushView)
                .on("end", brush);
        });
        //APPEND BACKGROUND
        background = parcoords.append("g")
            .attr("class", "background")
            .selectAll("path")
            .data(vetorDados)
            .enter().append("path")
            .attr("d", path);

        // ADD FOREGROUND LINES
        foreground = parcoords.append("g")
            .attr("class", "foreground")
            .selectAll("path")
            .data(vetorDados)
            .enter().append("path")
            .attr("d", path);

        // Add a group element for each trait.
        var g = parcoords.selectAll(".trait")
            .data(traits)
            .enter()
            .append("svg:g")
            .attr("class", "trait")
            .attr("transform", function (d) {
                return "translate(" + x(d) + ")";
            })
            .call(d3.drag()
                  .subject(function (d) {
                      return { x: x(d) };
                  })
                  .on("start", function (d) {
                      dragging[d] = x(d);
                      background.attr("visibility", "hidden");
                  })
                  .on("drag", function (d) {
                      //+10 e -10 para mudar com o primeiro e o ultimo
                      dragging[d] = Math.min(w + 10, Math.max(-10, d3.event.x));
                      foreground.attr("d", path);
                      traits.sort(function (a, b) {
                          return position(a) - position(b);
                      });
                      x.domain(traits);
                      g.attr("transform", function (d) {
                          return "translate(" + position(d) + ")";
                      });
                  })
                  .on("end", function (d) {
                      delete dragging[d];
                      transition(d3.select(this)).attr("transform", "translate(" + x(d) + ")");
                      transition(foreground).attr("d", path);
                      background
                          .attr("d", path)
                          .transition()
                          .delay(500)
                          .duration(0)
                          .attr("visibility", null);
                  })
		 );

        //BACKGROUND GRADIENT do eixo Sexo
        var defs = parcoords.append("defs");
        var gradient = defs.append("linearGradient")
            .attr("id", "svgGradient")
            .attr("x1", "50%")
            .attr("x2", "100%")
            .attr("y1", "50%")
            .attr("y2", "100%");
        gradient.append("stop")
            .attr('class', 'start')
            .attr("offset", "0%")
            .attr("stop-color", "blue")
            .attr("stop-opacity", 1);
        gradient.append("stop")
            .attr('class', 'end')
            .attr("offset", "100%")
            .attr("stop-color", "red")
            .attr("stop-opacity", 1);
        //Eixos
        g.append("svg:g")
            .attr("class", "axis")
            .each(function (col) {
                // Para remover os nomes das cidades
                if (col == "municipio") {
                    d3.select(this)
			.call(d3.axisLeft(y[col]))
			.selectAll("text").remove();
                }
                if (col == "Sexo") {
                    d3.select(this)
                        .attr("class", "eixoSexo")
                        .call(d3.axisLeft(y[col]))
                        .selectAll("text").remove();
                    d3.select(this)
			.call(d3.axisLeft(y[col])
			      .ticks(3));
                    d3.select(this)
                        .append("svg:text").text("M")
                        .attr("x", -9)
                        .attr("y", 10);
                    d3.select(this)
                        .append("svg:text").text("F")
                        .attr("x", -9)
                        .attr("y", h + 2);
                }
                else if (col == "Hora") {
                    d3.select(this).call(d3.axisLeft(y[col]).ticks(18));
                }
                else if (col == "Causador") {
                    // ALT
                    d3.select(this)
			.call(d3.axisLeft(y[col]))
			.selectAll("text")
			._groups[0].forEach(function (p) {
                            p.innerHTML = p.innerHTML.split(" ")[0];
			});
                }
                else {
                    d3.select(this).call(d3.axisLeft(y[col]));
                }
            })
        // Titulos dos eixos
            .append("svg:text")
            .attr("text-anchor", "middle")
            .attr("y", -15)
            .text(function (col) {
                return col;
            });

        // Add a brush for each axis.
        g.append("svg:g")
            .attr("class", "brush")
            .each(function (d) {
                d3.select(this).call(y[d].brush);
            })
            .selectAll("rect")
            .attr("x", -8)
            .attr("width", 16);

        function position(d) {
            var v = dragging[d];
            return v == null ? x(d) : v;
        }

        function transition(g) {
            return g.transition().duration(500);
        }
        // Returns the path for a given data point.

        function path(d) {
            return line(traits.map(function (p) {
                return [position(p), y[p](d[p])];
            }));
        }

        // BRUSH FUNCTIONS
        function brushstart() {
            d3.event.sourceEvent.stopPropagation();
        }

        function brushView() {
            var actives = [];
            //filter brushed extents
            parcoords.selectAll(".brush")
                .filter(function (d) {
                    return d3.brushSelection(this);
                })
                .each(function (d) {

                    actives.push({
                        dimension: d,
                        extent: d3.brushSelection(this)
                    });
                    dim = actives[0].dimension;
                });
            //set un-brushed foreground line disappear
            foreground.classed("fade", function (d, i) {
                return !actives.every(function (active) {
                    var dim = active.dimension;
                    return active.extent[0] <= y[dim](d[dim]) && y[dim](d[dim]) <= active.extent[1];
                });
            });
        }


        function brush() {
            var actives = [];
            //filter brushed extents
            parcoords.selectAll(".brush")
                .filter(function (d) {
                    return d3.brushSelection(this);
                })
                .each(function (d) {
                    actives.push({
                        dimension: d,
                        extent: d3.brushSelection(this)
                    });

                    var selected = vetorDados.filter(function (d) {
                        return actives.every(function (active) {
                            var dim = active.dimension;
                            return active.extent[0] <= y[dim](d[dim]) && y[dim](d[dim]) <= active.extent[1];
                        });
                    });

                    hideTableColNames();
                    d3.selectAll(".row_data").remove();

                    showTableColNames();

                    selected.forEach(function (d) {
                        var row = parcoordstable.append("tr")
                            .attr("class", "row_data");
                        traits.forEach(
                            function (string) {
                                row.append("td")
                                    .text(d[string]);
                            }
                        );
                    });

                });
            foreground.classed("fade", function (d, i) {
                return !actives.every(function (active) {
                    var dim = active.dimension;
                    return active.extent[0] <= y[dim](d[dim]) && y[dim](d[dim]) <= active.extent[1];
                });
            });
        }

        function hideTableColNames() {
            table.style("visibility", "hidden");
        }

        function showTableColNames() {
            table.style("visibility", "visible");
        }
    }
    // IMPORTANTE
    loadChart();
});
